<template>
<div :class="[
      type === 'textarea' ? 'hj-textarea' : 'hj-input',
      {
        'is-disabled': inputDisabled,
      }
    ]">
  <label v-if="labelText" :style="{width: labelWidth + 'px'}" :for="id">{{labelText}}</label>
  <input v-bind="$attrs" :style="{width: inputWidth + 'px'}" :id="id" :type="type" :maxlength="maxlength" :readonly="readonly" :disabled="inputDisabled" @compositionstart="handleCompositionStart" @compositionend="handleCompositionEnd" @input="handleInput" />
</div>
</template>

<script>
import {
  UPDATE_MODEL_EVENT
} from '../../../utils/constants.ts'
import {
  defineComponent,
  computed,
  watch,
  nextTick,
  ref,
  shallowRef,
  onMounted,
  onUpdated,
} from 'vue'

export default defineComponent({
  name: 'HjInput',
  props: {
    labelText: {
      type: String,
      default: '',
    },
    labelWidth: {
      type: String,
      default: "70",
    },
    inputWidth: {
      type: String,
      default: "200",
    },
    maxlength: {
      type: String,
      default: null,
    },
    modelValue: {
      type: [String, Number],
      default: '',
    },
    id: {
      type: String,
      default: null,
    },
    type: {
      type: String,
      default: 'text',
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    readonly: {
      type: Boolean,
      default: false,
    },
  },

  emits: [UPDATE_MODEL_EVENT, 'change', 'focus', 'blur', 'clear'],

  setup(props, ctx) {
    const inputDisabled = computed(() => props.disabled)
    const isComposing = ref(false)
    const input = ref(null)
    const textarea = ref(null)

    const inputOrTextarea = computed(() => input.value || textarea.value)
    const nativeInputValue = computed(() => String(props.modelValue))

    const handleCompositionStart = () => {
      isComposing.value = true
    }

    const handleCompositionEnd = event => {
      if (isComposing.value) {
        isComposing.value = false
        handleInput(event)
      }
    }

    const handleInput = event => {
      // should not emit input during composition
      if (isComposing.value) return

      // should remove the following line when we don't support IE
      if (event.target.value === nativeInputValue.value) return

      ctx.emit(UPDATE_MODEL_EVENT, event.target.value)

      // ensure native input value is controlled
      // see: https://github.com/ElemeFE/element/issues/12850
      nextTick(setNativeInputValue)
    }

    const setNativeInputValue = () => {
      const input = inputOrTextarea.value
      if (!input || input.value === nativeInputValue.value) return
      input.value = nativeInputValue.value
    }

    const handleChange = event => {
      console.log(event)
      ctx.emit('change', event.target.value)
    }

    watch(nativeInputValue, () => {
      setNativeInputValue()
    })

    onMounted(() => {
      setNativeInputValue()
    })

    return {
      inputDisabled,
      isComposing,
      input,
      textarea,
      inputOrTextarea,
      nativeInputValue,

      handleCompositionStart,
      handleCompositionEnd,
      setNativeInputValue,
      handleChange,
      handleInput,
    }
  },
})
</script>
